#ifndef JLIST_H
#define JLIST_H

#include <memory>
#include <vector>
#include <JXQCore/JContainerBase>
#include <JXQCore/JMetaType>
#include <JXQCore/JDebug>

namespace JXQ
{

template <typename T>
class JListPrivate
{
	explicit JListPrivate(size_t n);
	JListPrivate(const JListPrivate &other);
	JListPrivate(std::initializer_list<T> &_list);
	~JListPrivate();

	void operator=(const JListPrivate &other);
	void operator=(std::initializer_list<T> &_list);

	size_t insert(size_t index, T *data);
	size_t insert(size_t index, T **data, size_t length);
	size_t insert(size_t index, std::initializer_list<T> &_list);
	int erase(size_t index, bool deleteNode = true);
	int erase(size_t begin, size_t end);
	void clear();

	struct iteratorPrivate
	{
		JListPrivate<T> *p;
		mutable int index;
	};

	class iterator_base
	{
	protected:
		inline iterator_base(const JListPrivate<T> *p, int index);
		iterator_base(const iterator_base &other);
		iterator_base(iterator_base &&other) noexcept;
		inline virtual ~iterator_base() = 0;

	public:
		T &operator*();
		T *operator->();
		const T &operator*() const;
		const T *operator->() const;

	public:
		bool operator==(const iterator_base &other) const;
		bool operator!=(const iterator_base &other) const;
		const iterator_base &operator=(const iterator_base &other);
		const iterator_base &operator=(iterator_base &&other) noexcept;

	protected:
		friend class JList<T>;
		iteratorPrivate *d_ptr;
	};

	class iterator : public iterator_base
	{
	public:
		explicit iterator(const JListPrivate<T> *p, int index = 0);
		iterator(const iterator &other);
		iterator(iterator &&other);
		iterator &operator++();
		iterator &operator++(int);
		iterator &operator--();
		iterator &operator--(int);
		const iterator &operator++() const;
		const iterator &operator++(int) const;
		const iterator &operator--() const;
		const iterator &operator--(int) const;
		bool operator==(const iterator &other) const;
		bool operator!=(const iterator &other) const;
		const iterator &operator=(const iterator &other);
		const iterator &operator=(iterator &&other);
	};
	typedef const iterator  const_iterator;

	class reverse_iterator : public iterator_base
	{
	public:
		explicit reverse_iterator(const JListPrivate<T> *p);
		explicit reverse_iterator(const JListPrivate<T> *p, int index);
		reverse_iterator(const reverse_iterator &other);
		reverse_iterator(reverse_iterator &&other);
		reverse_iterator &operator++();
		reverse_iterator &operator++(int);
		reverse_iterator &operator--();
		reverse_iterator &operator--(int);
		const reverse_iterator &operator++() const;
		const reverse_iterator &operator++(int) const;
		const reverse_iterator &operator--() const;
		const reverse_iterator &operator--(int) const;
		bool operator==(const reverse_iterator &other) const;
		bool operator!=(const reverse_iterator &other) const;
		const reverse_iterator &operator=(const reverse_iterator &other);
		const reverse_iterator &operator=(reverse_iterator &&other);
	};
	typedef const reverse_iterator  const_reverse_iterator;

	friend class JList<T>;
	T** data;
	size_t size = 0;
	size_t capacity;
};

template <typename T>
class JList : public JListBase<T>
{
public:
	typedef typename JListPrivate<T>::iterator  iterator;
	typedef typename JListPrivate<T>::const_iterator  const_iterator;
	typedef typename JListPrivate<T>::reverse_iterator  reverse_iterator;
	typedef typename JListPrivate<T>::const_reverse_iterator  const_reverse_iterator;

public:
	explicit JList(size_t n = 1);
	JList(const JList &other);
	JList(JList &&other) noexcept;
	JList(std::initializer_list<T> _list);
	~JList();

	const JList &operator=(const JList &other);
	const JList &operator=(JList &&other);
	const JList &operator=(std::initializer_list<T> _list);

public:
	JList &append(T &&data);
	JList &append(const T &data);
	JList &append(const JList<T> &other);
	JList &append(std::initializer_list<T> _list);

	JList &operator<<(T &&data);
	JList &operator<<(const T &data);
	JList &operator<<(const JList<T> &other);
	JList &operator<<(std::initializer_list<T> _list);

public:
	iterator insert(const_iterator it, T &&data);
	iterator insert(const_iterator it, const T &data);
	iterator insert(const_iterator it, const JList<T> &other);
	iterator insert(const_iterator it, std::initializer_list<T> _list);

	iterator insert(size_t i, T &&data);
	iterator insert(size_t i, const T &data);
	iterator insert(size_t i, const JList<T> &other);
	iterator insert(size_t i, std::initializer_list<T> _list);

public:
	template <typename ...Args>
	iterator emplace(size_t i, Args&&...);

	template <typename ...Args>
	iterator emplace(const_iterator it, Args&&...);

	template <typename ...Args>
	JList &emplaceFront(Args&&...);

	template <typename ...Args>
	JList &emplaceBack(Args&&...);

public:
	iterator erase(const_iterator it);
	iterator erase(const_iterator first, const_iterator last);
	iterator erase(size_t i);
	iterator erase(size_t begin, size_t end);

	T popFront();
	T popBack();
	void clear();

public:
	void swap(JList<T> &other);
	T &operator[](int n);
	const T &operator[](int n) const;

public:
	iterator begin();
	const_iterator begin() const;
	const_iterator constBegin() const;

	iterator end();
	const_iterator end() const;
	const_iterator constEnd() const;

	reverse_iterator rBegin();
	const_reverse_iterator rBegin() const;
	const_reverse_iterator constRBegin() const;

	reverse_iterator rEnd();
	const_reverse_iterator rEnd() const;
	const_reverse_iterator constREnd() const;

	T &front();
	const T &front() const;

	T &back();
	const T &back() const;

public:
	size_t size() const;
	size_t length() const;
	size_t capacity() const;
	bool isEmpty() const;

private:
	JListPrivate<T> *pData;
};

template<typename T>
inline JListPrivate<T>::JListPrivate(size_t n) :
	data(new T*[1])
{
	if( n == 0 )
		n = 1;
	capacity = n;
}

template <typename T>
inline JListPrivate<T>::JListPrivate(const JListPrivate &other) :
	data(new T*[other.capacity]),
	size(other.size),
	capacity(other.capacity)
{
	for(size_t i=0; i<size; i++)
		data[i] = new T(*other.data[i]);
}

template <typename T>
inline JListPrivate<T>::JListPrivate(std::initializer_list<T> &_list)
{
	capacity = _list.size() << 1;
	data = new T*[capacity];
	size = _list.size();

	auto it = _list.begin();
	for(size_t i=0; i<size; i++, ++it)
		data[i] = new T(*it);
}

template <typename T>
inline JListPrivate<T>::~JListPrivate()
{
	clear();
	delete[] data;
}

template <typename T>
void JListPrivate<T>::operator=(const JListPrivate &other)
{
	size_t i = 0;

	if( capacity < other.size )
	{
		capacity = other.size << 1;
		T** tmp = new T*[capacity];

		for(; i<size and i<other.size; i++)
		{
			delete data[i];
			tmp[i] = new T(*other.data[i]);
		}

		for(size_t j=i; j<size; j++)
			delete data[j];

		for(; i<other.size; i++)
			tmp[i] = new T(*other.data[i]);

		delete[] data;
		data = tmp;
		size = other.size;
	}
	else
	{
		for(; i<size and i<other.size; i++)
		{
			delete data[i];
			data[i] = new T(*other.data[i]);
		}

		for(size_t j=i; j<size; j++)
			delete data[j];

		for(; i<other.size; i++)
			data[i] = new T(*other.data[i]);
		size = other.size;
	}
}

template <typename T>
void JListPrivate<T>::operator=(std::initializer_list<T> &_list)
{
	size_t l_size = _list.size();
	size_t i = 0;
	auto it = _list.begin();

	if( capacity < l_size )
	{
		capacity = l_size << 1;
		T** tmp = new T*[capacity];

		for(; i<size and i<l_size; i++, ++it)
		{
			delete data[i];
			tmp[i] = new T(*it);
		}

		for(int j=i; j<size; j++)
			delete data[j];

		for(; i<l_size; i++, ++it)
			tmp[i] = new T(*it);

		delete[] data;
		data = tmp;
		size = l_size;
	}
	else
	{
		for(; i<size and i<l_size; i++)
		{
			delete data[i];
			data[i] = new T(*it);
		}

		for(int j=i; j<size; j++)
			delete data[j];

		for(; i<l_size; i++, ++it)
			data[i] = new T(*it);
		size = l_size;
	}
}

template <typename T>
size_t JListPrivate<T>::insert(size_t index, T *data)
{
	if( index > size )
		index = size;

	size_t t_size = size + 1;
	if( t_size > capacity )
	{
		capacity = size << 1;
		while( t_size > capacity )
			capacity <<= 1;

		T** tmp = new T*[capacity];

		size_t i = 0;
		for(; i<index; i++)
			tmp[i] = this->data[i];

		tmp[i++] = data; //拷贝的过程中插入

		size++;
		for(; i<size; i++)
			tmp[i] = this->data[i-1];

		delete[] this->data;
		this->data = tmp;
	}
	else
	{
		for(size_t i=size++; i>index; i--)
			this->data[i] = this->data[i-1];
		this->data[index] = data;
	}
	return index;
}

template <typename T>
size_t JListPrivate<T>::insert(size_t index, T **data, size_t length)
{
	if( index > size )
		index = size;

	if( length == 0 )
		return index;

	size_t t_size = size + length;
	if( t_size > capacity )
	{
		capacity = size << 1;
		while( t_size > capacity )
			capacity <<= 1;

		T** tmp = new T*[capacity];

		size_t i = 0;
		for(; i<index; i++)
			tmp[i] = this->data[i];

		for(int j=0; j<length; j++)
			tmp[i++] = new T(*data[j]); //拷贝的过程中插入

		size += length;
		for(; i<size; i++)
			tmp[i] = this->data[i-length];

		delete[] this->data;
		this->data = tmp;
	}
	else
	{
		size_t i = size;
		size += length;

		for(; i>index; i--)
			this->data[i] = this->data[i-length];

		for(int j=0; j<length; j++)
			this->data[i++] = data[j];
	}
	return index;
}

template <typename T>
size_t JListPrivate<T>::insert(size_t index, std::initializer_list<T> &_list)
{
	if( index > size )
		index = size;

	size_t l_size = _list.size();
	if( l_size == 0 )
		return index;

	size_t t_size = size + l_size;
	if( t_size > capacity )
	{
		capacity = size << 1;
		while( t_size > capacity )
			capacity <<= 1;

		T** tmp = new T*[capacity];

		size_t i = 0;
		for(; i<index; i++)
			tmp[i] = data[i];

		for(auto &j : _list)
			tmp[i++] = new T(j); //拷贝的过程中插入

		size += l_size;
		for(; i<l_size; i++)
			tmp[i] = data[i-l_size];

		delete[] data;
		data = tmp;
	}
	else
	{
		size_t i = size;
		size += l_size;

		for(; i>index; i--)
			data[i] = data[i-l_size];

		for(auto &j : _list)
			data[i++] = new T(j);
	}
	return index;
}

template <typename T>
int JListPrivate<T>::erase(size_t index, bool deleteNode)
{
	if( index >= this->size )
		index = this->size - 1;

	if( deleteNode )
		delete data[index];

	--size;
	for(size_t i=index; i<this->size; i++)
		data[i] = data[i+1];

	if( index >= this->size )
		index = -1;
	return index;
}

template <typename T>
int JListPrivate<T>::erase(size_t begin, size_t end)
{
	if( begin >= this->size or begin > end )
		return -1;

	if( end >= this->size )
		end = this->size - 1;

	int size = end - begin + 1;
	for(size_t i=begin; i<=end; i++)
		delete data[i];

	this->size -= size;
	for(size_t i=begin; i<this->size; i++)
		data[i] = data[i+size];

	if( begin >= this->size )
		begin = -1;
	return begin;
}

template <typename T>
void JListPrivate<T>::clear()
{
	for(size_t i=0; i<size; i++)
		delete data[i];
}

template <typename T>
inline JListPrivate<T>::iterator_base::iterator_base(const JListPrivate<T> *p, int index) :
	d_ptr(new iteratorPrivate {J_CCT(JListPrivate<T>*,p), index}) {}

template <typename T>
inline JListPrivate<T>::iterator_base::iterator_base(const iterator_base &other) :
	d_ptr(new iteratorPrivate {J_CCT(JListPrivate<T>*,other.d_ptr->p), other.d_ptr->index}) {}

template <typename T>
inline JListPrivate<T>::iterator_base::iterator_base(iterator_base &&other) noexcept
{ operator=(std::forward<iterator_base>(other)); }

template <typename T>
inline JListPrivate<T>::iterator_base::~iterator_base()
{ if( d_ptr != nullptr ) delete d_ptr; }

template <typename T>
inline T &JListPrivate<T>::iterator_base::operator*()
{ return *d_ptr->p->data[d_ptr->index]; }

template <typename T>
inline T *JListPrivate<T>::iterator_base::operator->()
{ return d_ptr->p->data[d_ptr->index]; }

template <typename T>
inline const T &JListPrivate<T>::iterator_base::operator*() const
{ return d_ptr->p->data[d_ptr->index]; }

template <typename T>
inline const T *JListPrivate<T>::iterator_base::operator->() const
{ return d_ptr->p->data[d_ptr->index]; }

template<typename T>
inline bool JListPrivate<T>::iterator_base::
operator==(const iterator_base &other) const
{ return d_ptr->index == other.d_ptr->index; }

template <typename T>
inline bool JListPrivate<T>::iterator_base::
operator!=(const iterator_base &other) const
{ return d_ptr->index != other.d_ptr->index; }

template <typename T>
inline const typename JListPrivate<T>::iterator_base&
JListPrivate<T>::iterator_base::operator=(const iterator_base &other)
{
	d_ptr->p = other.d_ptr->p;
	d_ptr->index = other.d_ptr->index;
	if( d_ptr->index >= J_SCT(int, d_ptr->p->size) )
		d_ptr->index = -1;
	return *this;
}

template <typename T>
inline const typename JListPrivate<T>::iterator_base&
JListPrivate<T>::iterator_base::operator=(iterator_base &&other) noexcept
{
	d_ptr = other.d_ptr;
	other.d_ptr = nullptr;
	return *this;
}

template <typename T>
inline JListPrivate<T>::iterator::
iterator(const JListPrivate<T> *p, int index) :
	JListPrivate<T>::iterator_base(p,index) {}

template <typename T>
inline JListPrivate<T>::iterator::iterator(const iterator &other) :
	JListPrivate<T>::iterator_base(other) {}

template <typename T>
inline JListPrivate<T>::iterator::iterator(iterator &&other) :
	JListPrivate<T>::iterator_base(std::forward<iterator>(other)) {}

template <typename T>
inline typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator++()
{
	if( ++this->d_ptr->index >= J_SCT(int, this->d_ptr->p->size) )
		this->d_ptr->index = -1;
	return *this;
}

template <typename T>
inline typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator++(int)
{
	auto tmp = *this;
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return tmp;
}

template <typename T>
inline typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator--()
{
	if( this->d_ptr->index > -1 )
		--this->d_ptr->index;
	else
		this->d_ptr->index = this->d_ptr->p->size - 1;
	return *this;
}

template <typename T>
inline typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator--(int)
{
	auto tmp = *this;
	operator--();
	return tmp;
}

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator++() const
{
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return *this;
}

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator++(int) const
{
	auto tmp = *this;
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return tmp;
}

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator--() const
{
	if( this->d_ptr->index > -1 )
		--this->d_ptr->index;
	else
		this->d_ptr->index = this->d_ptr->p->size - 1;
	return *this;
}

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator--(int) const
{
	auto tmp = *this;
	operator--();
	return tmp;
}

template <typename T>
inline bool JListPrivate<T>::iterator::
operator==(const iterator &other) const
{ return iterator_base::operator==(other); }

template <typename T>
inline bool JListPrivate<T>::iterator::
operator!=(const iterator &other) const
{ return iterator_base::operator!=(other); }

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator=(const iterator &other)
{ iterator_base::operator=(other); return *this; }

template <typename T>
inline const typename JListPrivate<T>::iterator&
JListPrivate<T>::iterator::operator=(iterator &&other)
{ iterator_base::operator=(std::forward<iterator>(other)); return *this; }

template <typename T>
inline JListPrivate<T>::reverse_iterator::
	reverse_iterator(const JListPrivate<T> *p) :
	JListPrivate<T>::iterator_base(p, p->size - 1) {}

template <typename T>
inline JListPrivate<T>::reverse_iterator::
	reverse_iterator(const JListPrivate<T> *p, int index) :
	JListPrivate<T>::iterator_base(p, index) {}

template <typename T>
inline JListPrivate<T>::reverse_iterator::
	reverse_iterator(const reverse_iterator &other) :
	JListPrivate<T>::iterator_base(other) {}

template <typename T>
inline JListPrivate<T>::reverse_iterator::
	reverse_iterator(reverse_iterator &&other) :
	JListPrivate<T>::iterator_base(std::forward<reverse_iterator>(other)) {}

template <typename T>
inline typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator++()
{
	if( this->d_ptr->index > -1 )
		--this->d_ptr->index;
	else
		this->d_ptr->index = this->d_ptr->p->size - 1;
	return *this;
}

template <typename T>
inline typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator++(int)
{
	auto tmp = *this;
	operator++();
	return tmp;
}

template <typename T>
inline typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator--()
{
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return *this;
}

template<typename T>
inline typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator--(int)
{
	auto tmp = *this;
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return tmp;
}

template <typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator++() const
{
	if( this->d_ptr->index > -1 )
		--this->d_ptr->index;
	else
		this->d_ptr->index = this->d_ptr->p->size - 1;
	return *this;
}

template<typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator++(int) const
{
	auto tmp = *this;
	operator++();
	return tmp;
}

template <typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator--() const
{
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return *this;
}

template <typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator--(int) const
{
	auto tmp = *this;
	if( ++this->d_ptr->index >= this->d_ptr->p->size )
		this->d_ptr->index = -1;
	return tmp;
}

template <typename T>
inline bool JListPrivate<T>::reverse_iterator::
operator==(const reverse_iterator &other) const
{ return iterator_base::operator==(other); }

template <typename T>
inline bool JListPrivate<T>::reverse_iterator::
operator!=(const reverse_iterator &other) const
{ return iterator_base::operator!=(other); }

template <typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator=(const reverse_iterator &other)
{ iterator_base::operator=(other); return *this; }

template <typename T>
inline const typename JListPrivate<T>::reverse_iterator&
JListPrivate<T>::reverse_iterator::operator=(reverse_iterator &&other)
{ iterator_base::operator=(std::forward<reverse_iterator>(other)); return *this; }

template <typename T>
inline JList<T>::JList(size_t n) :
	pData(new JListPrivate<T>(n)) {}

template <typename T>
inline JList<T>::JList(const JList &other) :
	pData(new JListPrivate<T>(*other.pData)) {}

template <typename T>
inline JList<T>::JList(JList &&other) noexcept :
	pData(other.pData) { other.pData = nullptr; }

template <typename T>
inline JList<T>::JList(std::initializer_list<T> _list) :
	pData(new JListPrivate<T>(_list)) {}

template <typename T>
inline JList<T>::~JList()
{
	if( pData != nullptr )
		delete pData;
}

template <typename T>
const JList<T> &JList<T>::operator=(const JList &other)
{
	*pData = *other.pData;
	return *this;
}

template <typename T>
const JList<T> &JList<T>::operator=(JList &&other)
{
	pData = other.pData;
	other.pData = nullptr;
	return *this;
}

template <typename T>
const JList<T> &JList<T>::operator=(std::initializer_list<T> _list)
{
	*pData = _list;
	return *this;
}

template <typename T>
inline JList<T> &JList<T>::append(T &&data)
{
	pData->insert(pData->size, new T(std::forward<T>(data)));
	return *this;
}

template <typename T>
inline JList<T> &JList<T>::append(const T &data)
{
	pData->insert(pData->size, new T(data));
	return *this;
}

template <typename T>
inline JList<T> &JList<T>::append(const JList<T> &other)
{
	pData->insert(other.size(), other.pData->data, other.size());
	return *this;
}

template <typename T>
inline JList<T> &JList<T>::append(std::initializer_list<T> _list)
{
	pData->insert(pData->size, _list);
	return *this;
}

template <typename T>
inline JList<T> &JList<T>::operator<<(T &&data)
{
	return append(std::forward<T>(data));
}

template<typename T>
inline JList<T> &JList<T>::operator<<(const T &data)
{
	return append(data);
}

template <typename T>
inline JList<T> &JList<T>::operator<<(const JList<T> &other)
{
	return append(other);
}

template <typename T>
inline JList<T> &JList<T>::operator<<(std::initializer_list<T> _list)
{
	return append(_list);
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(const_iterator it, T &&data)
{
	return iterator(this->pData, pData->insert(it.d_ptr->index, new T(std::forward<T>(data))));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(const_iterator it, const T &data)
{
	return iterator(this->pData, pData->insert(it.d_ptr->index, new T(data)));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(const_iterator it, const JList<T> &other)
{
	return iterator(this->pData, pData->insert(it.d_ptr->index, other.pData->data, other.size()));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::
insert(const_iterator it, std::initializer_list<T> _list)
{
	return iterator(this->pData, pData->insert(it.d_ptr->index, _list));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(size_t i, T &&data)
{
	return iterator(this->pData, pData->insert(i, new T(std::forward<T>(data))));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(size_t i, const T &data)
{
	return iterator(this->pData, pData->insert(i, new T(data)));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::insert(size_t i, const JList<T> &other)
{
	return iterator(this->pData, pData->insert(i, other.pData->data, other.size()));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::
insert(size_t i, std::initializer_list<T> _list)
{
	return iterator(this->pData, pData->insert(i, _list));
}

template <typename T>
template <typename ...Args>
inline typename JList<T>::iterator JList<T>::emplace(size_t i, Args&&...args)
{
	return iterator(this->pData, pData->insert(i, new T(std::forward<Args>(args)...)));
}

template <typename T>
template <typename ...Args>
inline typename JList<T>::iterator JList<T>::emplace(const_iterator it, Args&&...args)
{
	return iterator(this->pData, pData->insert(it.d_ptr->index, new T(std::forward<Args>(args)...)));
}

template <typename T>
template <typename ...Args>
inline JList<T> &JList<T>::emplaceFront(Args&&...args)
{
	pData->insert(0, new T(std::forward<Args>(args)...));
	return *this;
}

template <typename T>
template <typename ...Args>
inline JList<T> &JList<T>::emplaceBack(Args&&...args)
{
	pData->insert(pData->size, new T(std::forward<Args>(args)...));
	return *this;
}

template <typename T>
inline typename JList<T>::iterator
JList<T>::erase(const_iterator it)
{
	return iterator(this->pData, pData->erase(it.d_ptr->index));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::
	erase(const_iterator first, const_iterator last)
{
	return iterator(this->pData, pData->erase(first.d_ptr->index, last.d_ptr->index));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::erase(size_t i)
{
	return iterator(this->pData, pData->erase(i));
}

template <typename T>
inline typename JList<T>::iterator JList<T>::erase(size_t begin, size_t end)
{
	return iterator(this->pData, pData->erase(begin, end));
}

template <typename T>
inline T JList<T>::popFront()
{
#if 0
	assert( pData->size == 0 );
#endif
	std::unique_ptr<T> p(pData->data[0]);
	pData->erase(0, false);
	return std::move(*p);
}

template <typename T>
inline T JList<T>::popBack()
{
#if 0
	assert( pData->size == 0 );
#endif
	int index = pData->size - 1;
	std::unique_ptr<T> p(pData->data[index]);
	pData->erase(index, false);
	return std::move(*p);
}

template <typename T>
inline void JList<T>::clear()
{
	pData->clear();
}

template <typename T>
inline void JList<T>::swap(JList<T> &other)
{
	auto tmp = pData;
	pData = other.pData;
	other.pData = tmp;
}

template <typename T>
inline T &JList<T>::operator[](int n)
{
#if 0
	assert( n>=0 and n<pData->size );
#endif
	return *pData->data[n];
}

template <typename T>
inline const T &JList<T>::operator[](int n) const
{
#if 0
	assert( n>=0 and n<pData->size );
#endif
	return *pData->data[n];
}

template <typename T>
inline typename JList<T>::iterator JList<T>::begin()
{ return iterator(this->pData); }

template <typename T>
inline typename JList<T>::const_iterator JList<T>::begin() const
{ return const_iterator(this->pData); }

template <typename T>
inline typename JList<T>::const_iterator JList<T>::constBegin() const
{ return begin(); }

template <typename T>
inline typename JList<T>::iterator JList<T>::end()
{ return iterator(this->pData, -1); }

template <typename T>
inline typename JList<T>::const_iterator JList<T>::end() const
{ return const_iterator(this->pData, -1); }

template <typename T>
inline typename JList<T>::const_iterator JList<T>::constEnd() const
{ return end(); }

template <typename T>
inline typename JList<T>::reverse_iterator JList<T>::rBegin()
{ return reverse_iterator(this->pData); }

template <typename T>
inline typename JList<T>::const_reverse_iterator JList<T>::rBegin() const
{ return const_reverse_iterator(this->pData); }

template <typename T>
inline typename JList<T>::const_reverse_iterator JList<T>::constRBegin() const
{ return rBegin(); }

template <typename T>
inline typename JList<T>::reverse_iterator JList<T>::rEnd()
{ return reverse_iterator(this->pData, -1); }

template <typename T>
inline typename JList<T>::const_reverse_iterator JList<T>::rEnd() const
{ return const_reverse_iterator(this->pData); }

template <typename T>
inline typename JList<T>::const_reverse_iterator JList<T>::constREnd() const
{ return rEnd(); }

template <typename T>
inline T &JList<T>::front()
{
#if 0
	assert( pData->size == 0 );
#endif
	return *pData->data[0];
}

template <typename T>
inline const T &JList<T>::front() const
{
#if 0
	assert( pData->size == 0 );
#endif
	return *pData->data[0];
}

template <typename T>
inline T &JList<T>::back()
{
#if 0
	assert( pData->size == 0 );
#endif
	return *pData->data[pData->size - 1];
}

template <typename T>
inline const T &JList<T>::back() const
{
#if 0
	assert( pData->size == 0 );
#endif
	return *pData->data[pData->size - 1];
}

template <typename T>
inline size_t JList<T>::size() const
{ return pData->size; }

template <typename T>
inline size_t JList<T>::length() const
{ return pData->size; }

template <typename T>
inline size_t JList<T>::capacity() const
{ return pData->capacity; }

template <typename T>
inline bool JList<T>::isEmpty() const
{ return pData->size == 0; }

/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/

template <typename T>
JDebug &operator<<(JDebug &d, const JList<T> *list)
{
	std::cout << "JList<" << JTypeInfo::getName<T>() << ">( ";
	for(auto &str : *list)
		d << str;
	return d << ")";
}

template <typename T>
inline JDebug &operator<<(JDebug &&d, const JList<T> *list)
{ return d << list; }

template <typename T>
inline JDebug &operator<<(JDebug &d, const JList<T> &list)
{ return d << &list; }

template <typename T>
inline JDebug &operator<<(JDebug &&d, const JList<T> &list)
{ return d << &list; }

} //namespace JXQ


#endif //JLIST_H
